package main

import (
	"fmt"
	"math/rand"
	"sync"
	"sync/atomic"
	"time"
)

// 服务器节点
type ServiceNode struct {
	Url   string
	Alive bool
}

// 健康检查
func (v *ServiceNode) IsHealth() bool {
	random := rand.Int()
	if random%2 == 0 {
		fmt.Println("check Health not alive url=" + v.Url)
		return false
	}
	return true
}

// 服务器节点列表
type ServiceNodeGroup struct {
	NodeList    []*ServiceNode
	index       atomic.Int64
	NodeListMap map[string]*ServiceNode
	mu          sync.Mutex
}

// 添加节点
func (v *ServiceNodeGroup) AddNode(url string) {
	v.mu.Lock()
	defer v.mu.Unlock()

	_, ok := v.NodeListMap[url]
	if ok {
		v.NodeListMap[url].Alive = true
		return
	}

	node := ServiceNode{
		Url:   url,
		Alive: true,
	}
	v.NodeList = append(v.NodeList, &node)
	v.NodeListMap[url] = &node
}

// 移除节点
func (v *ServiceNodeGroup) RemoveNode(url string) {
	v.mu.Lock()
	defer v.mu.Unlock()
	v.NodeListMap[url].Alive = false
}

// 获取节点
func (v *ServiceNodeGroup) GetOneNode() *ServiceNode {
	var serviceNode *ServiceNode
	maxLen := len(v.NodeList)
	serviceNode = v.NodeList[v.index.Load()%(int64(maxLen))] // 循环数组
	if serviceNode.IsHealth() {
		v.index.Add(1)
	} else {
		v.index.Add(1)
		serviceNode = v.NodeList[v.index.Load()%(int64(maxLen))]
	}
	return serviceNode
}

// 健康检查
func (v *ServiceNodeGroup) CheckHealth() {
	go func() {
		for _, node := range v.NodeList {
			if !node.IsHealth() {
				v.RemoveNode(node.Url)
			} else {
				v.AddNode(node.Url)
			}
		}
		time.Sleep(1 * time.Second)
	}()
}
